home *** CD-ROM | disk | FTP | other *** search
/ Freelog 125 / Freelog_MarsAvril2015_No125.iso / Musique / Quod Libet / quodlibet-3.3.0-installer.exe / bin / quodlibet / plugins / __init__.pyc (.txt) next >
Python Compiled Bytecode  |  2014-12-31  |  17KB  |  491 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.7)
  3.  
  4. from quodlibet import config
  5. from quodlibet import util
  6. from quodlibet.util.modulescanner import ModuleScanner
  7. from quodlibet.util.dprint import print_d
  8. from quodlibet.qltk.ccb import ConfigCheckButton
  9.  
  10. def init(folders = None, disable_plugins = False):
  11.     '''folders: list of paths to look for plugins
  12.     disable_plugins: disables all plugins, but does not forget which
  13.     plugins are enabled.
  14.     '''
  15.     if disable_plugins:
  16.         folders = []
  17.     manager = PluginManager.instance = PluginManager(folders)
  18.     return manager
  19.  
  20.  
  21. def quit():
  22.     PluginManager.instance.save()
  23.     PluginManager.instance.quit()
  24.     PluginManager.instance = None
  25.  
  26.  
  27. class PluginImportException(Exception):
  28.     desc = ''
  29.     
  30.     def __init__(self, desc, *args, **kwargs):
  31.         super(PluginImportException, self).__init__(desc)
  32.         self.desc = desc
  33.  
  34.     
  35.     def should_show(self):
  36.         '''If the error description should be shown to the user'''
  37.         return True
  38.  
  39.  
  40.  
  41. class PluginNotSupportedError(PluginImportException):
  42.     '''To hide the plugin (e.g. on Windows)'''
  43.     
  44.     def __init__(self):
  45.         super(PluginNotSupportedError, self).__init__('not supported')
  46.  
  47.     
  48.     def should_show(self):
  49.         return False
  50.  
  51.  
  52.  
  53. class MissingModulePluginException(PluginImportException):
  54.     '''Consistent Exception for reporting missing modules for plugins'''
  55.     
  56.     def __init__(self, module_name):
  57.         msg = _("Couldn't find module '{module}'. Perhaps you need to install the package?").format(module = module_name)
  58.         super(MissingModulePluginException, self).__init__(msg)
  59.  
  60.  
  61.  
  62. class MissingGstreamerElementPluginException(PluginImportException):
  63.     '''Consistent Exception for reporting missing Gstreamer elements for
  64.     plugins'''
  65.     
  66.     def __init__(self, element_name):
  67.         msg = _("Couldn't find GStreamer element '{element}'.").format(element = element_name)
  68.         super(MissingGstreamerElementPluginException, self).__init__(msg)
  69.  
  70.  
  71.  
  72. def migrate_old_config():
  73.     active = []
  74.     old_keys = [
  75.         'songsmenuplugins',
  76.         'eventplugins',
  77.         'editingplugins',
  78.         'playorderplugins']
  79.     for key in old_keys:
  80.         key = 'active_' + key
  81.         
  82.         try:
  83.             active.extend(config.get('plugins', key).splitlines())
  84.         except config.Error:
  85.             continue
  86.  
  87.         config._config.remove_option('plugins', key)
  88.     
  89.     if active:
  90.         config.set('plugins', 'active_plugins', '\n'.join(active))
  91.  
  92.  
  93. def list_plugins(module):
  94.     """Return all objects of the module that satisfy the basic
  95.     plugin needs: id, name and don't start with '_'
  96.  
  97.     If '__all__' is defined, only plugins in '__all__' will be loaded.
  98.     """
  99.     
  100.     try:
  101.         objs = [ getattr(module, attr) for attr in module.__all__ ]
  102.     except AttributeError:
  103.         objs = [ getattr(module, attr) for attr in vars(module) if attr.startswith('_') ]
  104.  
  105.     ok = []
  106.     for obj in objs:
  107.         if not hasattr(obj, 'PLUGIN_ID') or hasattr(obj, 'PLUGIN_NAME'):
  108.             obj.PLUGIN_NAME = obj.PLUGIN_ID
  109.         ok.append(obj)
  110.         continue
  111.     
  112.     return ok
  113.  
  114.  
  115. class PluginModule(object):
  116.     
  117.     def __init__(self, name, module):
  118.         self.name = name
  119.         self.module = module
  120.         self.plugins = [ Plugin(cls) for cls in list_plugins(module) ]
  121.  
  122.  
  123.  
  124. class Plugin(object):
  125.     
  126.     def __init__(self, plugin_cls):
  127.         self.cls = plugin_cls
  128.         self.handlers = []
  129.         self.instance = None
  130.  
  131.     
  132.     def __repr__(self):
  133.         return '<%s id=%r name=%r>' % (type(self).__name__, self.id, self.name)
  134.  
  135.     
  136.     def id(self):
  137.         return self.cls.PLUGIN_ID
  138.  
  139.     id = property(id)
  140.     
  141.     def name(self):
  142.         return self.cls.PLUGIN_NAME
  143.  
  144.     name = property(name)
  145.     
  146.     def description(self):
  147.         return getattr(self.cls, 'PLUGIN_DESC', None)
  148.  
  149.     description = property(description)
  150.     
  151.     def tags(self):
  152.         tags = getattr(self.cls, 'PLUGIN_TAGS', [])
  153.         if isinstance(tags, basestring):
  154.             tags = [
  155.                 tags]
  156.         return tags
  157.  
  158.     tags = property(tags)
  159.     
  160.     def icon(self):
  161.         return getattr(self.cls, 'PLUGIN_ICON', None)
  162.  
  163.     icon = property(icon)
  164.     
  165.     def get_instance(self):
  166.         '''A singleton'''
  167.         if not getattr(self.cls, 'PLUGIN_INSTANCE', False):
  168.             return None
  169.         if None.instance is None:
  170.             
  171.             try:
  172.                 obj = self.cls()
  173.             except:
  174.                 util.print_exc()
  175.                 return None
  176.  
  177.             self.instance = obj
  178.         return self.instance
  179.  
  180.  
  181.  
  182. class PluginHandler(object):
  183.     '''A plugin handler can choose to handle plugins, as well as control
  184.     their enabled state.'''
  185.     
  186.     def plugin_handle(self, plugin):
  187.         '''Returns `True` IFF this handler can handle `plugin`'''
  188.         raise NotImplementedError
  189.  
  190.     
  191.     def plugin_enable(self, plugin):
  192.         '''Called to enable / register `plugin`'''
  193.         raise NotImplementedError
  194.  
  195.     
  196.     def plugin_disable(self, plugin):
  197.         '''Called to disable / de-register `plugin`'''
  198.         raise NotImplementedError
  199.  
  200.  
  201.  
  202. class PluginManager(object):
  203.     """
  204.     The manager takes care of plugin loading/reloading. Interested plugin
  205.     handlers can register them self to get called when plugins get enabled
  206.     or disabled.
  207.  
  208.     Plugins get exposed when at least one handler shows interest
  209.     in them (by returning True in the handle method).
  210.  
  211.     Plugins have to be a class which defines PLUGIN_ID, PLUGIN_NAME.
  212.     Plugins that have a true PLUGIN_INSTANCE attribute get instantiated on
  213.     enable and the enabled/disabled methods get called.
  214.  
  215.     If plugin handlers want a plugin instance, they have to call
  216.     Plugin.get_instance() to get a singleton.
  217.  
  218.     handlers need to implement the following methods:
  219.  
  220.         handler.plugin_handle(plugin)
  221.             Needs to return True if the handler should be called
  222.             whenever the plugin's enabled status changes.
  223.  
  224.         handler.plugin_enable(plugin)
  225.             Gets called if the plugin gets enabled.
  226.  
  227.         handler.plugin_disable(plugin)
  228.             Gets called if the plugin gets disabled.
  229.             Should remove all references.
  230.     """
  231.     CONFIG_SECTION = 'plugins'
  232.     CONFIG_OPTION = 'active_plugins'
  233.     instance = None
  234.     
  235.     def __init__(self, folders = None):
  236.         '''folders is a list of paths that will be scanned for plugins.
  237.         Plugins in later paths will be preferred if they share a name.
  238.         '''
  239.         super(PluginManager, self).__init__()
  240.         if folders is None:
  241.             folders = []
  242.         self._PluginManager__scanner = ModuleScanner(folders)
  243.         self._PluginManager__modules = { }
  244.         self._PluginManager__handlers = []
  245.         self._PluginManager__enabled = set()
  246.         self._PluginManager__restore()
  247.  
  248.     
  249.     def rescan(self):
  250.         '''Scan for plugin changes or to initially load all plugins'''
  251.         print_d('Rescanning..')
  252.         (removed, added) = self._PluginManager__scanner.rescan()
  253.         reload_ids = []
  254.         for name in removed:
  255.             if name not in added:
  256.                 continue
  257.             mod = self._PluginManager__modules[name]
  258.             for plugin in mod.plugins:
  259.                 if self.enabled(plugin):
  260.                     reload_ids.append(plugin.id)
  261.                     continue
  262.         
  263.         for name in removed:
  264.             self._PluginManager__remove_module(name)
  265.         
  266.         self._PluginManager__enabled.update(reload_ids)
  267.         for name in added:
  268.             new_module = self._PluginManager__scanner.modules[name]
  269.             self._PluginManager__add_module(name, new_module.module)
  270.         
  271.         print_d('Rescanning done.')
  272.  
  273.     
  274.     def _modules(self):
  275.         return self._PluginManager__scanner.modules.itervalues()
  276.  
  277.     _modules = property(_modules)
  278.     
  279.     def _plugins(self):
  280.         '''All registered plugins'''
  281.         plugins = []
  282.         for module in self._PluginManager__modules.itervalues():
  283.             for plugin in module.plugins:
  284.                 plugins.append(plugin)
  285.             
  286.         
  287.         return plugins
  288.  
  289.     _plugins = property(_plugins)
  290.     
  291.     def plugins(self):
  292.         '''Returns a list of plugins with active handlers'''
  293.         return [ p for p in self._plugins if p.handlers ]
  294.  
  295.     plugins = property(plugins)
  296.     
  297.     def register_handler(self, handler):
  298.         '''
  299.         Registers a handler, attaching it to any current plugins it
  300.         advertises that it can handle
  301.  
  302.         `handler` should probably be a `PluginHandler`
  303.         '''
  304.         print_d('Registering handler: %r' % type(handler).__name__)
  305.         self._PluginManager__handlers.append(handler)
  306.         for plugin in self._plugins:
  307.             if not handler.plugin_handle(plugin):
  308.                 continue
  309.             if plugin.handlers:
  310.                 plugin.handlers.append(handler)
  311.                 if self.enabled(plugin):
  312.                     handler.plugin_enable(plugin)
  313.                 
  314.             plugin.handlers.append(handler)
  315.             if self.enabled(plugin):
  316.                 self.enable(plugin, True, force = True)
  317.                 continue
  318.  
  319.     
  320.     def save(self):
  321.         print_d('Saving plugins: %d active' % len(self._PluginManager__enabled))
  322.         config.set(self.CONFIG_SECTION, self.CONFIG_OPTION, '\n'.join(self._PluginManager__enabled))
  323.  
  324.     
  325.     def enabled(self, plugin):
  326.         '''Returns if the plugin is enabled.'''
  327.         if not plugin.handlers:
  328.             return False
  329.         return None.id in self._PluginManager__enabled
  330.  
  331.     
  332.     def enable(self, plugin, status, force = False):
  333.         '''Enable or disable a plugin.'''
  334.         if not force and self.enabled(plugin) == bool(status):
  335.             return None
  336.         if not None:
  337.             print_d('Disable %r' % plugin.id)
  338.             for handler in plugin.handlers:
  339.                 handler.plugin_disable(plugin)
  340.             
  341.             self._PluginManager__enabled.discard(plugin.id)
  342.             instance = plugin.instance
  343.             if instance and hasattr(instance, 'disabled'):
  344.                 
  345.                 try:
  346.                     instance.disabled()
  347.                 except Exception:
  348.                     util.print_exc()
  349.                 
  350.  
  351.             else:
  352.                 print_d('Enable %r' % plugin.id)
  353.                 obj = plugin.get_instance()
  354.                 if obj and hasattr(obj, 'enabled'):
  355.                     
  356.                     try:
  357.                         obj.enabled()
  358.                     except Exception:
  359.                         util.print_exc()
  360.                     
  361.  
  362.                 for handler in plugin.handlers:
  363.                     handler.plugin_enable(plugin)
  364.                 
  365.                 self._PluginManager__enabled.add(plugin.id)
  366.  
  367.     
  368.     def failures(self):
  369.         '''module name: list of error message text lines'''
  370.         errors = { }
  371.         for name, error in self._PluginManager__scanner.failures.iteritems():
  372.             exception = error.exception
  373.             if isinstance(exception, PluginImportException):
  374.                 if not exception.should_show():
  375.                     continue
  376.                 errors[name] = [
  377.                     exception.desc]
  378.                 continue
  379.             errors[name] = error.traceback
  380.         
  381.         return errors
  382.  
  383.     failures = property(failures)
  384.     
  385.     def quit(self):
  386.         '''Disable plugins and tell all handlers to clean up'''
  387.         for name in self._PluginManager__modules.keys():
  388.             self._PluginManager__remove_module(name)
  389.         
  390.  
  391.     
  392.     def __remove_module(self, name):
  393.         plugin_module = self._PluginManager__modules.pop(name)
  394.         for plugin in plugin_module.plugins:
  395.             if plugin.handlers:
  396.                 self.enable(plugin, False)
  397.                 continue
  398.  
  399.     
  400.     def __add_module(self, name, module):
  401.         plugin_mod = PluginModule(name, module)
  402.         self._PluginManager__modules[name] = plugin_mod
  403.         for plugin in plugin_mod.plugins:
  404.             handlers = []
  405.             for handler in self._PluginManager__handlers:
  406.                 if handler.plugin_handle(plugin):
  407.                     handlers.append(handler)
  408.                     continue
  409.             if handlers:
  410.                 plugin.handlers = handlers
  411.                 if self.enabled(plugin):
  412.                     self.enable(plugin, True, force = True)
  413.                 
  414.  
  415.     
  416.     def __restore(self):
  417.         migrate_old_config()
  418.         active = config.get(self.CONFIG_SECTION, self.CONFIG_OPTION, '').splitlines()
  419.         self._PluginManager__enabled.update(active)
  420.         print_d('Restoring plugins: %d' % len(self._PluginManager__enabled))
  421.         for plugin in self._plugins:
  422.             if self.enabled(plugin):
  423.                 self.enable(plugin, True, force = True)
  424.                 continue
  425.  
  426.  
  427. PM = PluginManager
  428.  
  429. class PluginConfigMixin(object):
  430.     '''
  431.     Mixin for storage and editing of plugin config in a standard way
  432.     Will use `CONFIG_SECTION`, if defined, for storing config, otherwise,
  433.     it will base the keys on `PLUGIN_ID`.
  434.     '''
  435.     
  436.     def _config_key(cls, name):
  437.         
  438.         try:
  439.             prefix = cls.CONFIG_SECTION
  440.         except AttributeError:
  441.             prefix = cls.PLUGIN_ID.lower().replace(' ', '_')
  442.  
  443.         return '%s_%s' % (prefix, name)
  444.  
  445.     _config_key = classmethod(_config_key)
  446.     
  447.     def config_get(cls, name, default = ''):
  448.         '''Gets a config string value for this plugin'''
  449.         return config.get(PM.CONFIG_SECTION, cls._config_key(name), default)
  450.  
  451.     config_get = classmethod(config_get)
  452.     
  453.     def config_set(cls, name, value):
  454.         '''Saves a config string value for this plugin'''
  455.         
  456.         try:
  457.             config.set(PM.CONFIG_SECTION, cls._config_key(name), value)
  458.         except config.Error:
  459.             print_d("Couldn't set config item '%s' to %r" % (name, value))
  460.  
  461.  
  462.     config_set = classmethod(config_set)
  463.     
  464.     def config_get_bool(cls, name, default = False):
  465.         '''Gets a config boolean for this plugin'''
  466.         return config.getboolean(PM.CONFIG_SECTION, cls._config_key(name), default)
  467.  
  468.     config_get_bool = classmethod(config_get_bool)
  469.     
  470.     def config_entry_changed(self, entry, key):
  471.         '''React to a change in an gtk.Entry (by saving it to config)'''
  472.         if entry.get_property('sensitive'):
  473.             self.config_set(key, entry.get_text())
  474.  
  475.     
  476.     def ConfigCheckButton(cls, label, name, default = False):
  477.         '''
  478.         Create a new `ConfigCheckButton` for `name`, pre-populated correctly
  479.         '''
  480.         option = cls._config_key(name)
  481.         
  482.         try:
  483.             config.getboolean(PM.CONFIG_SECTION, option)
  484.         except config.Error:
  485.             cls.config_set(name, default)
  486.  
  487.         return ConfigCheckButton(label, PM.CONFIG_SECTION, option, populate = True)
  488.  
  489.     ConfigCheckButton = classmethod(ConfigCheckButton)
  490.  
  491.